#ifndef MATRIX_J66BTRW4

#define MATRIX_J66BTRW4

#include <string>
#include <fstream>
#include <iostream>

#include <vector>
#include <set>

class Matrix
{
public:
    Matrix ( );
    /*
     * @brief this constructor creates a sub matrix of the Matrix m
     * 
     * @param matrix - the main matrix
     * @param col - the sub matrix elements, same as in the mainMatrix
     */
    Matrix ( Matrix *m, std::vector<unsigned int> col );
    virtual ~Matrix ();

    
    /** 
     * @brief set distance (d) from x to y
     * 
     * @param x id node
     * @param y id node
     * @param d distance
     */
    void set(unsigned int x, unsigned int y, double d);
    
    void setFictifBounds();
    
    void setElementFromMainMatrix( unsigned int element );
    
    void removeFictifBounds();
    
    void setSize(unsigned int size);
    /** 
     * @brief get distance from x to y
     * 
     * @param x id node
     * @param y id node
     * 
     * @return distance
     */
    inline double get(const unsigned int &x, const unsigned int &y) const
    {
        return _vvMatrix[x][y];
    }

    void randomGen(unsigned int size, int maxVal = 100);

	void randomGen2(unsigned int size, int maxVal = 100);
	
	void randomGen3(unsigned int size, double &maxDelta);

    void randomRobinsonMatrix(unsigned int size);
    
    std::vector<unsigned int> getColsInMatrix();
    
    inline unsigned int getSize() const
    {
        return _vvMatrix.size();
    }

    void clean();
    /** 
     * @brief show matrix (exemple for cout)
     * 
     * @param os output stream
     * @param m matrix
     * 
     * @return output stream
     */
    friend std::ostream& operator << (std::ostream& os, const Matrix& m);

    
    /** 
     * @brief set matix by input stream (exemple for cin)
     * 
     * @param os input stream
     * @param m matrix
     * 
     * @return input stream
     */
    friend std::istream& operator >> (std::istream& os, Matrix& m);

private:
    double _dMaxDist;
    std::vector<std::vector<double> > _vvMatrix;
    /**
     * @brief this vector contains the indexes of the elements from the main matrix, it's used to construct
     * the submatrix */
    std::vector<unsigned int> _colsInMatrix;
    /**
     * @brief this is the main matrix from wich we construct the submatrix */
    Matrix *_mainMatrix;
};

/**
 * Show matrix
 */
std::ostream& operator << (std::ostream& os, const Matrix& m);

/**
 * set matrix
 */
std::istream& operator >> (std::istream& is, Matrix& m);


#endif /* end of include guard: MATRIX_J66BTRW4 */
